package xyz.bali16.module.advise.service;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gitee.starblues.bootstrap.annotation.AutowiredType;
import com.gitee.starblues.spring.MainApplicationContext;
import com.gitee.starblues.spring.SpringBeanFactory;
import com.google.common.base.Preconditions;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.util.HtmlUtils;
import xyz.bali16.application.core.exception.BusinessException;
import xyz.bali16.application.core.model.UserVo;
import xyz.bali16.application.core.utils.AuthUtils;
import xyz.bali16.application.core.utils.SensitiveFilter;
import xyz.bali16.application.core.utils.TimeUtil;
import xyz.bali16.application.entity.User;
import xyz.bali16.application.mapper.UserMapper;
import xyz.bali16.application.service.UserService;
import xyz.bali16.module.advise.entity.Advise;
import xyz.bali16.module.advise.mapper.AdviseMapper;
import xyz.bali16.module.advise.model.AdviseAddParam;
import xyz.bali16.module.advise.model.AdvisePageParam;


import java.util.List;

import static xyz.bali16.application.constant.ForumConstant.ENTITY_TYPE_POST;


/**
 * 留言相关
 */
@Service
public class AdviseServiceImpl extends ServiceImpl<AdviseMapper, Advise> implements AdviseService {

    @AutowiredType(AutowiredType.Type.MAIN)
    @Autowired
    UserMapper userMapper;

    @Autowired
    private AdviseMapper adviseMapper;

    @AutowiredType(AutowiredType.Type.MAIN)
    @Autowired
    private SensitiveFilter sensitiveFilter;
    @Autowired
    private MainApplicationContext context;


    @Override
    public IPage<Advise> getPage(AdvisePageParam param) {
        IPage<?> page = new Page<>(param.getCurrent(), param.getSize());
        return this.baseMapper.getPage(page, param);
    }

    /**
     * 查询留言的数量
     *
     * @param parentId
     * @return
     */
    @Override
    public Integer getAdviseCount(String parentId) {
        return adviseMapper.selectCountByEntity(parentId);
    }


    /**
     * 添加留言（需要事务管理）
     *
     * @param param
     * @return
     */
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)
    @Override
    public void addAdvise(AdviseAddParam param) throws Exception {

        Advise advise = new Advise();
        BeanUtils.copyProperties(param, advise);
        String nickname = advise.getNickname();

        if (advise == null) {
            throw new IllegalArgumentException("参数不能为空");
        }

        if (nickname == null) {
            String username = AuthUtils.getCurrentUsername();
            if (!StringUtils.isBlank(username)) {
                User user = userMapper.getUserByUsername(username);
                if (user == null) {
                    throw new BusinessException("留言用户信息不正确");
                }
                nickname = user.getName();
            }
        }
        advise.setNickname(nickname);
        // Html 标签转义
        advise.setContent(HtmlUtils.htmlEscape(advise.getContent()));
        // 敏感词过滤
        advise.setContent(sensitiveFilter.filter(advise.getContent()));
        advise.setGmtCreated(TimeUtil.getNowTimeToSeconds());
        // 添加留言
        save(advise);
    }


    @Override
    public void delete(String adviseId) throws Exception {
        if (adviseId == null) {
            return;
        }
        Wrapper<Advise> wrapper = Wrappers.<Advise>lambdaQuery().eq(Advise::getParentId, adviseId);
        // 移除所有子留言
        List<Advise> child_advises = adviseMapper.selectList(wrapper);
        for (Advise advise : child_advises) {
            removeById(advise.getId());
        }

        removeById(adviseId);
    }


    @Override
    public Integer getYesterdayCount() {
        DateTime yesterday = DateUtil.yesterday();
        return this.lambdaQuery()
                .ge(Advise::getGmtCreated, yesterday)
                .count();
    }

    @Override
    public Integer countAdvise() {
        return lambdaQuery().select(Advise::getId).count();
    }

}
